package gwtappcontainer.server.apis.admin;

import static org.junit.Assert.assertTrue;
import gwtappcontainer.server.apis.admin.Roles.Role;
import gwtappcontainer.shared.apis.APIResponse;
import gwtappcontainer.shared.apis.APIResponse.Status;
import gwtappcontainer.shared.apis.admin.UserProp;
import gwtappcontainer.testhelpers.APITestHelper;
import gwtappcontainer.testhelpers.Util;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

//this uses apitesthelper (rather than using mockgatekeeper directly)
public class AdminAPITest2 {
	private final APITestHelper helper = new APITestHelper();
	
	@Before
	public void setUp() {
		helper.setUp();
	}
	
	@After 
	public void tearDown() {
		helper.tearDown();
	}
	
	@Test
	public void canViewRolesByEmail() {
		helper.loginAsDeveloper();
		User user = UserServiceFactory.getUserService().getCurrentUser();
		
		AdminAPI api = new AdminAPI();
		APIResponse resp = api.getRolesForUser(user.getEmail());
		
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		UserProp prop = (UserProp) resp.object;
		
		assertTrue(Util.isRolePresent(prop.roles, Role.DEVELOPER.toString()));
		
		//try with portal user just to be sure
		helper.loginAsPortalUser();
		user = UserServiceFactory.getUserService().getCurrentUser();
		
		resp = api.getRolesForUser(user.getEmail());
		
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		prop = (UserProp) resp.object;
		
		assertTrue(Util.isRolePresent(prop.roles, Role.PORTAL_USER.toString()));				
	}
	
	@Test
	public void canViewRolesForLoggedInUser() {
		helper.loginAsPortalAdmin();
		User user = UserServiceFactory.getUserService().getCurrentUser();
		
		AdminAPI api = new AdminAPI();
		APIResponse resp = api.getRolesForLoggedInUser(user);
		
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		UserProp prop = (UserProp) resp.object;
		
		assertTrue(Util.isRolePresent(prop.roles, Role.PORTAL_ADMIN.toString()));
	}
	
	@Test
	public void loginNotRequiredToViewRolesByEmail() {
		helper.loginAsDeveloper();
		User user = UserServiceFactory.getUserService().getCurrentUser();
		String email = user.getEmail();
		
		helper.logout();
		
		AdminAPI api = new AdminAPI();
		APIResponse resp = api.getRolesForUser(email);
		
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		UserProp prop = (UserProp) resp.object;
		
		assertTrue(Util.isRolePresent(prop.roles, Role.DEVELOPER.toString()));
	}
	
	@Test
	public void viewingCurrentRolesWithoutLoginThrowsAuthenticationError() {
		helper.logout();		
		
		AdminAPI api = new AdminAPI();
		User user = UserServiceFactory.getUserService().getCurrentUser();
		
		assertTrue(null == user);
		APIResponse resp = api.getRolesForLoggedInUser(user);
		
		assertTrue(resp.statusCode == Status.ERROR_LOGIN_REQUIRED);
	}
	
	@Test
	public void portalAdminCanChangeUserPermission() {
		
		//1. create user
		String email = "test@example.com";
		AdminAPI adminApi = new AdminAPI();
		adminApi.addUser(email, helper.loginAsPortalAdmin());
		
		//2. assign role
		User user = helper.loginAsPortalAdmin();
		String role = Role.PORTAL_READONLY.toString();
		APIResponse resp = adminApi.assignRoleToUser(email, role, user); 				
		
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		//ensure role is correctly added
		UserProp prop = (UserProp) adminApi.getRolesForUser(email).object;		
		assertTrue(Util.isRolePresent(prop.roles, role));
		
		//3. unassign role
		resp = adminApi.unassignRoleToUser(email, role, user);
		assertTrue(resp.statusCode == Status.SUCCESS);
		
		prop = (UserProp) adminApi.getRolesForUser(email).object;
		assertTrue(false == Util.isRolePresent(prop.roles, role));				
	}
	
	@Test
	public void developerPortalUserPortalReadOnlyCannotChangeUserPermission() {
		//1. create user
		String email = "test@example.com";
		AdminAPI adminApi = new AdminAPI();
		adminApi.addUser(email, helper.loginAsPortalAdmin());
		
		//2. assign
		//developer
		String role = Role.PORTAL_READONLY.toString();		
		APIResponse response = adminApi.assignRoleToUser(email, role, 
			helper.loginAsDeveloper());
		assertTrue(response.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);
		
		
		//portal user
		response = adminApi.assignRoleToUser(email, role, 
			helper.loginAsPortalUser());
		assertTrue(response.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);
		
		
		//portal readonly		
		response = adminApi.assignRoleToUser(email, role, 
			helper.loginAsPortalReadOnly());
		assertTrue(response.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);
		
		
		UserProp prop = (UserProp) adminApi.getRolesForUser(email).object;		
		assertTrue(false == Util.isRolePresent(prop.roles, role));
		
		//3. unassign
		//developer		
		APIResponse resp = adminApi.unassignRoleToUser(email, role, 
				helper.loginAsDeveloper());
		assertTrue(resp.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);
		
		//portal user
		resp = adminApi.unassignRoleToUser(email, role, 
				helper.loginAsPortalUser());
		assertTrue(resp.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);
		
		//portal readonly
		resp = adminApi.unassignRoleToUser(email, role, 
				helper.loginAsPortalReadOnly());
		assertTrue(resp.statusCode == Status.ERROR_INSUFFICIENT_PERMISSION);							
	}		
}
